1
/******************************** Module Header ********************************\
2 * Module Name: AsymmetricsAlgorithmForm.cs
3 * Project: CSEncryption
4 * Copyright (c) Microsoft Corporation.
6 * Asymmetric algorithms:
7 * It uses a public and private key pair to encrypt and decrypt data. The public
8 * key is made available to anyone and is used to encrypt data to be sent to
9 * the owner of the private key. The private key, as the name implies, is kept
10 * private. The private key is used to decrypt the data and will only work if
11 * the correct public key was used when encrypting the data. The private key is
12 * the only key that will allow data encrypted with the public key to be
13 * decrypted. The following public-key algorithms are available for use in
18 * This Form demonstrates how to use RSA algorithm to encrypt &
19 * decrypt data. I refer to some code from the book .NET Security and
23 * 1 Input the data into textbox so as to create message object
24 * 2 Click encrypt button
25 * 2.1 Serialize the message object to get plaintext data as byte array
26 * 2.2 Encrypt data by using RSACryptoServiceProvider object
27 * 2.3 Update UI display
28 * 3 Click decrypt button to decrypt) data
29 * 3.1 Create RSACryptoServiceProvider object. Initialize it with key, IV,etc
30 * 3.2 Decrypt ciphered data to get plain text
31 * 3.3 Update UI display
33 * This source is subject to the Microsoft Public License.
34 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
35 * All other rights reserved.
38 * * 4/14/2009 09:00 AM Riquel Dong Created
39 \*******************************************************************************/
41 #region Using Directives
43 using System
.Collections
.Generic
;
44 using System
.ComponentModel
;
49 using System
.Windows
.Forms
;
50 using System
.Security
.Cryptography
;
52 using System
.Runtime
.Serialization
.Formatters
.Binary
;
56 namespace CSEncryption
58 public partial class AsymmetricAlgorithmForm
: Form
60 // Byte array to contain ciphered message
61 List
<byte[]> cipherArray
;
62 List
<byte[]> recoveredArray
;
64 public AsymmetricAlgorithmForm()
66 InitializeComponent();
67 cipherArray
= new List
<byte[]>();
68 recoveredArray
= new List
<byte[]>();
72 /// Generate the public and private key for data encryption and decryption
74 private void GenerateNewRSAParammeters()
78 // Create a RSA obj to perform asymmetric RSA algorithm
79 RSACryptoServiceProvider rsa
= new RSACryptoServiceProvider();
81 // Display publicprivate key in textbox control
82 tbxRSAParameters
.Text
= rsa
.ToXmlString(true);
84 // Save the public and private keys to a XML file
85 using (StreamWriter sw
= new StreamWriter("PublicPrivateKey.xml"))
87 sw
.Write(tbxRSAParameters
.Text
);
90 // Save the public key to a XML file for encryption
91 using (StreamWriter sw
= new StreamWriter("PublicOnlyKey.xml"))
93 sw
.Write(rsa
.ToXmlString(false));
99 recoveredArray
.Clear();
100 btnEncrypt
.Enabled
= true;
101 btnDecrypt
.Enabled
= false;
105 MessageBox
.Show(ex
.Message
);
110 /// Clear output value in textbox
112 private void ClearOutputFields()
114 tbxIntegerPart
.Text
= string.Empty
;
115 tbxMessagePart
.Text
= string.Empty
;
116 tbxCiphertextasByteArray
.Text
= string.Empty
;
117 tbxPlaintextasBytesArray
.Text
= string.Empty
;
121 /// Encrypt plaintext via public key.
122 /// This method is used just for demo. In real scenario we use symmetric
123 /// algorithm to encrypt data and use asymmetric algorithm to encrypt the
124 /// secret key used by symmetric algorithm
126 private void btnEncrypt_Click(object sender
, EventArgs e
)
129 if (string.IsNullOrEmpty(tbxInputMessage
.Text
) ||
130 !int.TryParse(tbxInputInterger
.Text
, out number
))
132 MessageBox
.Show("Invalid parameters!");
136 // Clear old output in the textbox control
139 Message msg
= new Message();
141 msg
.MessageBody
= tbxInputMessage
.Text
.Trim();
145 /////////////////////////////////////////////////////////////////
146 // Create a RSACryptoServiceProvider object and initialize it
147 // with a public key.
150 RSACryptoServiceProvider rsa
= new RSACryptoServiceProvider();
151 String publicOnlyKeyXml
= string.Empty
;
152 using (StreamReader sr
= new StreamReader("PublicOnlyKey.xml"))
154 publicOnlyKeyXml
= sr
.ReadToEnd();
156 rsa
.FromXmlString(publicOnlyKeyXml
);
159 /////////////////////////////////////////////////////////////////
160 // Serialize message object to get plaintext as byte array.
163 BinaryFormatter bf
= new BinaryFormatter();
164 byte[] plainBytes
= null;
165 using (MemoryStream stream
= new MemoryStream())
167 bf
.Serialize(stream
, msg
);
168 plainBytes
= stream
.ToArray();
172 /////////////////////////////////////////////////////////////////
173 // Encrypt plaintext data via public key. Because there is the
174 // length limit in asymmetric algorithm, I split byte array to
175 // encrypt every small part byte array. In real scenario we
176 // should use symmetric algorithm to encrypt large quantities
177 // of data and use asymmetric algorithm to encrypt secret key
178 // used by symmetric algorithm.
183 if (plainBytes
.Length
> 80)
185 byte[] partPlainBytes
;
187 while (plainBytes
.Length
- index
> 0)
189 if (plainBytes
.Length
- index
> 80)
191 partPlainBytes
= new byte[80];
195 partPlainBytes
= new byte[plainBytes
.Length
- index
];
197 for (int i
= 0; i
< 80 && (index
+ i
) < plainBytes
.Length
; i
++)
198 partPlainBytes
[i
] = plainBytes
[index
+ i
];
199 cipherbytes
= rsa
.Encrypt(partPlainBytes
, false);
200 length
+= cipherbytes
.Length
;
201 cipherArray
.Add(cipherbytes
);
207 /////////////////////////////////////////////////////////////////
208 // Display plaintext and ciphered data in UI.
211 byte[] cipheredPlaintext
= new byte[length
];
213 for (int i
= 0; i
< cipherArray
.Count
; i
++)
215 for (int j
= 0; j
< cipherArray
[i
].Length
; j
++)
217 cipheredPlaintext
[index
+ j
] = cipherArray
[i
][j
];
219 index
+= cipherArray
[i
].Length
;
222 // Display ciphered message in textbox control as byte array
223 StringBuilder sb
= new StringBuilder();
224 for (Int32 i
= 0; i
< cipheredPlaintext
.Length
; i
++)
226 sb
.Append(string.Format("{0:X2} ", cipheredPlaintext
[i
]));
228 tbxCiphertextasByteArray
.Text
= sb
.ToString();
230 // Display plaintext in textbox control as byte array
231 sb
= new StringBuilder();
232 for (Int32 i
= 0; i
< plainBytes
.Length
; i
++)
234 sb
.Append(string.Format("{0:X2} ", plainBytes
[i
]));
236 tbxPlaintextasBytesArray
.Text
= sb
.ToString();
237 btnDecrypt
.Enabled
= true;
238 btnEncrypt
.Enabled
= false;
242 // Display the error information to user
243 MessageBox
.Show(ex
.Message
);
248 /// Decrypt the ciphered data via private key
250 private void btnDecrypt_Click(object sender
, EventArgs e
)
254 /////////////////////////////////////////////////////////////////
255 // Create a RSACryptoServiceProvider object and initialize it
256 // with a public-private key pair.
259 RSACryptoServiceProvider rsa
= new RSACryptoServiceProvider();
260 String publicPrivateKeyXml
= string.Empty
;
261 using (StreamReader sr
= new StreamReader("PublicPrivateKey.xml"))
263 publicPrivateKeyXml
= sr
.ReadToEnd();
265 rsa
.FromXmlString(publicPrivateKeyXml
);
266 recoveredArray
.Clear();
269 /////////////////////////////////////////////////////////////////
270 // Get cipherd data as byte array and use the
271 // RSACryptoServiceProvider object to decrypt it.
275 for (int i
= 0; i
< cipherArray
.Count
; i
++)
277 byte[] partRecoveredPlainBytes
= rsa
.Decrypt(cipherArray
[i
], false);
278 recoveredArray
.Add(partRecoveredPlainBytes
);
279 length
+= partRecoveredPlainBytes
.Length
;
281 byte[] recoveredPlaintext
= new byte[length
];
283 for (int i
= 0; i
< recoveredArray
.Count
; i
++)
285 for (int j
= 0; j
< recoveredArray
[i
].Length
; j
++)
287 recoveredPlaintext
[index
+ j
] = recoveredArray
[i
][j
];
289 index
+= recoveredArray
[i
].Length
;
293 /////////////////////////////////////////////////////////////////
294 // Deserialize plaintext data to create message object and
295 // Display the data in UI.
298 BinaryFormatter bf
= new BinaryFormatter();
299 using (MemoryStream stream
= new MemoryStream())
301 stream
.Write(recoveredPlaintext
, 0, recoveredPlaintext
.Length
);
303 Message msgobj
= (Message
)bf
.Deserialize(stream
);
304 tbxIntegerPart
.Text
= msgobj
.Num
.ToString();
305 tbxMessagePart
.Text
= msgobj
.MessageBody
;
308 btnDecrypt
.Enabled
= false;
309 btnEncrypt
.Enabled
= true;
313 MessageBox
.Show(ex
.Message
);
317 private void btnNewRSAParameters_Click(object sender
, EventArgs e
)
319 GenerateNewRSAParammeters();
322 private void tbxInputInterger_TextChanged(object sender
, EventArgs e
)
325 btnDecrypt
.Enabled
= false;
326 btnEncrypt
.Enabled
= true;
329 private void tbxInputMessage_TextChanged(object sender
, EventArgs e
)
332 btnDecrypt
.Enabled
= false;
333 btnEncrypt
.Enabled
= true;
336 private void AsymmetricAlgorithmForm_Load(object sender
, EventArgs e
)
338 GenerateNewRSAParammeters();
339 btnEncrypt
.Enabled
= true;
340 btnDecrypt
.Enabled
= false;